<template>
  <div class="captcha-container">
    <canvas
      ref="canvasRef"
      :width="width"
      :height="height"
      class="captcha-canvas"
      @click="refreshCaptcha"
    ></canvas>
    <div class="captcha-controls">
      <el-button size="small" @click="refreshCaptcha" type="text">
        <el-icon><Refresh /></el-icon>
        刷新
      </el-button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'
import { Refresh } from '@element-plus/icons-vue'

interface Props {
  width?: number
  height?: number
  length?: number
}

const props = withDefaults(defineProps<Props>(), {
  width: 120,
  height: 40,
  length: 4
})

const emit = defineEmits<{
  'update:captchaText': [value: string]
}>()

const canvasRef = ref<HTMLCanvasElement>()
const captchaText = ref('')

// 生成随机验证码
const generateCaptcha = () => {
  const canvas = canvasRef.value
  if (!canvas) return

  const ctx = canvas.getContext('2d')
  if (!ctx) return

  // 清空画布
  ctx.clearRect(0, 0, props.width, props.height)

  // 生成随机验证码文本
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let text = ''
  for (let i = 0; i < props.length; i++) {
    text += chars.charAt(Math.floor(Math.random() * chars.length))
  }
  captchaText.value = text

  // 设置背景
  ctx.fillStyle = '#f0f0f0'
  ctx.fillRect(0, 0, props.width, props.height)

  // 绘制干扰线
  for (let i = 0; i < 3; i++) {
    ctx.strokeStyle = `rgb(${Math.random() * 255},${Math.random() * 255},${Math.random() * 255})`
    ctx.lineWidth = 1
    ctx.beginPath()
    ctx.moveTo(Math.random() * props.width, Math.random() * props.height)
    ctx.lineTo(Math.random() * props.width, Math.random() * props.height)
    ctx.stroke()
  }

  // 绘制干扰点
  for (let i = 0; i < 30; i++) {
    ctx.fillStyle = `rgb(${Math.random() * 255},${Math.random() * 255},${Math.random() * 255})`
    ctx.fillRect(Math.random() * props.width, Math.random() * props.height, 1, 1)
  }

  // 绘制验证码文字
  ctx.font = `${props.height * 0.6}px Arial`
  ctx.textBaseline = 'middle'
  
  for (let i = 0; i < text.length; i++) {
    ctx.fillStyle = `rgb(${Math.random() * 100},${Math.random() * 100},${Math.random() * 100})`
    ctx.save()
    ctx.translate(
      (props.width / props.length) * i + (props.width / props.length) / 2,
      props.height / 2
    )
    ctx.rotate((Math.random() - 0.5) * 0.3)
    ctx.fillText(text[i], 0, 0)
    ctx.restore()
  }

  // 发送验证码文本给父组件
  emit('update:captchaText', captchaText.value)
}

// 刷新验证码
const refreshCaptcha = () => {
  generateCaptcha()
}

// 监听属性变化
watch(() => props.length, () => {
  generateCaptcha()
})

onMounted(() => {
  generateCaptcha()
})

// 暴露方法给父组件
defineExpose({
  refreshCaptcha,
  getCaptchaText: () => captchaText.value
})
</script>

<style scoped>
.captcha-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.captcha-canvas {
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  cursor: pointer;
  background: #f0f0f0;
}

.captcha-canvas:hover {
  border-color: #409eff;
}

.captcha-controls {
  display: flex;
  justify-content: center;
}
</style> 